package com.corejsf;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.enterprise.context.SessionScoped;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import javax.sql.DataSource;

/**
 * This bean stores user form inputs from the Login form. Checks input
 * credentials against database, authorizes access to pages.
 *
 * @author Vukasin Simic
 * @version 1.0
 */
@Named("credentials")
@SessionScoped
public class Credentials implements Serializable {

    /**
     * serialVersionUID.
    */
    private static final long serialVersionUID = -7552420403156964863L;
    /**
     * Unique username of a user.
     *
     * Used as a login credential.
     */
    private String username;
    /**
     * User account password.
     *
     * Used as a login credential.
     */
    private String password;
    /**
     * User last name, used primarily for greetings.
     */
    private String lastName;
    /**
     * User first name, used primarily for greetings.
     */
    private String firstName;
    /**
     * Admin authorization. Grants special privileges.
     */
    private boolean admin;
    /**
     *
     */
    private int employeeNumber;

    /**
     * Max number of digits to pad employee number to with zeroes.
     */
    private static final int EMPNUMDIGITS = 5;

    /**
     * Max number of digits to pad employee number to with zeroes.
     */
    private boolean loggedIn = false;

    /**
     * DataSource for JBoss AS 7.1 connection pool.
     */
    @Resource(mappedName = "java:jboss/datasources/vvdb")
    private DataSource dataSource;

    /**
     * User attempt to login with provided credentials.
     *
     * @return navigation outcome string
     */
    public String login() {
        Connection connection = null;
        PreparedStatement stmt = null;
        String result = "invalid";
        try {
            try {
                connection = dataSource.getConnection();
                try {
                    stmt = connection.prepareStatement("SELECT * FROM Users "
                            + "WHERE UserName = ? AND Password = ?");
                    stmt.setString(1, this.username);
                    stmt.setString(2, this.password);
                    ResultSet rs = stmt.executeQuery();

                    if (rs.next()) {
                        loggedIn = true;
                        this.lastName = rs.getString("LastName");
                        this.firstName = rs.getString("FirstName");
                        this.admin = rs.getBoolean("Admin");
                        this.employeeNumber = rs.getInt("EmployeeNumber");
                        result = "valid";
                    }

                } finally {
                    if (stmt != null) {
                        stmt.close();
                    }

                }
            } finally {
                if (connection != null) {
                    connection.close();
                }
            }
        } catch (SQLException ex) {
            System.out.println("Error in login()");
            ex.printStackTrace();
        }
        return result;
    }

    /**
     * Terminates session.
     *
     * @return "login"
     */
    public String logout() {
        setLoggedIn(false);
        FacesContext.getCurrentInstance().getExternalContext()
                .invalidateSession();
        return "login";
    }

    /**
     * Gets username form input.
     *
     * @return unique username of a user account.
     */
    public String getUsername() {
        return username;
    }

    /**
     * Sets username of user account.
     *
     * @param username entered into form field
     */
    public void setUsername(final String username) {
        this.username = username;
    }

    /**
     * Gets password form input.
     *
     * @return password
     */
    public String getPassword() {
        return password;
    }

    /**
     * Sets password of user account.
     *
     * @param password
     *            form input
     */
    public void setPassword(final String password) {
        this.password = password;
    }

    /**
     * Gets last name form input.
     *
     * @return lastName
     */
    public String getLastName() {
        return lastName;
    }

    /**
     * Sets last name of user account.
     *
     * @param lastName form input
     */
    public void setLastName(final String lastName) {
        this.lastName = lastName;
    }

    /**
     * Gets first name form input.
     *
     * @return firstName
     */
    public String getFirstName() {
        return firstName;
    }

    /**
     * Sets first name of user account.
     *
     * @param firstName form input
     */
    public void setFirstName(final String firstName) {
        this.firstName = firstName;
    }

    /**
     * Gets admin form input.
     *
     * @return admin
     */
    public boolean isAdmin() {
        return admin;
    }

    /**
     * Sets admin authorization for user account.
     *
     * @param isAdmin
     *            form input
     */
    public void setAdmin(final boolean isAdmin) {

        this.admin = isAdmin;
    }

    /**
     * Returns employee number in padded string format.
     *
     * @return numString
     */
    public String getEmployeeNumberAsString() {
        String numString = Integer.toString(employeeNumber);
        int padding = EMPNUMDIGITS - numString.length();
        if (padding > 0) {
            numString = new String(new char[padding]).replace("\0", "0")
                    + numString;
        }
        return numString;
    }

    /**
     * Returns employee number.
     *
     * @return employeeNumber
     */
    public int getEmployeeNumber() {
        return employeeNumber;
    }

    /**
     * Sets employee number.
     *
     * @param employeeNumber to set
     */
    public void setEmployeeNumber(int employeeNumber) {
        this.employeeNumber = employeeNumber;
    }

    /**
     * Returns whether user is logged in.
     *
     * @return loggedIn
     */
    public boolean isLoggedIn() {
        return loggedIn;
    }

    /**
     * Sets whether user is logged in or not.
     *
     * @param loggedIn to set
     */
    public void setLoggedIn(boolean loggedIn) {
        this.loggedIn = loggedIn;
    }


}
